<?php

/**
 * @copyright Michiel Hakvoort 2010
 * @license http://www.opensource.org/licenses/bsd-license.php New BSD
 * @package mangrove
 * @subpackage grove
 * @filesource
 */

/*
 * Copyright (c) 2010 Michiel Hakvoort
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

namespace mg;

class Feedback {

    const FEEDBACK_INFO		= 'info';
    const FEEDBACK_WARNING	= 'warning';
    const FEEDBACK_ERROR	= 'error';
    const FEEDBACK_DEBUG	= 'debug';

    private $messages = null;

    public function __construct() {
        $this->messages = array();
    }

    public function addInfoMessage($object, $message) {
        $this->addMessage($object, $message, self :: FEEDBACK_INFO);
    }

    public function addDebugMessage($object, $message) {
        $this->addMessage($object, $message, self :: FEEDBACK_DEBUG);
    }

    public function addErrorMessage($object, $message) {
        $this->addMessage($object, $message, self :: FEEDBACK_ERROR);
    }

    public function addWarningMessage($object, $message) {
        $this->addMessage($object, $message, self :: FEEDBACK_WARNING);
    }

    public function addMessage($object, $message, $type = self :: FEEDBACK_INFO) {
        $arguments = array();

        if($message instanceof ParameterizedMessage) {
            $arguments = $message->arguments;
            $message = $message->message;
        }

        switch($type) {
            case self :: FEEDBACK_INFO :
                $message = new InfoMessage($message, $arguments);
                break;
            case self :: FEEDBACK_DEBUG :
                $message = new DebugMessage($message, $arguments);
                break;
            case self :: FEEDBACK_WARNING :
                $message = new WarningMessage($message, $arguments);
                break;
            case self :: FEEDBACK_ERROR :
                $message = new ErrorMessage($message, $arguments);
                break;
            default :
                throw new Exception('Unknown feedback type');
        }

        $hash = spl_object_hash($object);

        $this->messages[$hash][$type][] = $message;
    }

    public function hasMessages($object, $type = null) {
        $hash = spl_object_hash($object);

        if($type === null) {
            return isset($this->messages[$hash]);
        }

        switch($type) {
            case self :: FEEDBACK_INFO :
            case self :: FEEDBACK_DEBUG :
            case self :: FEEDBACK_WARNING :
            case self :: FEEDBACK_ERROR :
                break;
            default :
                throw new Exception('Unknown feedback type');
        }

        return isset($this->messages[$hash][$type]);
    }

    public function hasInfoMessages($object) {
        return $this->hasMessages($object, self :: FEEDBACK_INFO);
    }

    public function hasDebugMessages($object) {
        return $this->hasMessages($object, self :: FEEDBACK_DEBUG);
    }

    public function hasWarningMessages($object) {
        return $this->hasMessages($object, self :: FEEDBACK_WARNING);
    }

    public function hasErrorMessages($object) {
        return $this->hasMessages($object, self :: FEEDBACK_ERROR);
    }

    public function getMessages($object, $type = self :: FEEDBACK_INFO) {
        switch($type) {
            case self :: FEEDBACK_INFO :
            case self :: FEEDBACK_DEBUG :
            case self :: FEEDBACK_WARNING :
            case self :: FEEDBACK_ERROR :
                break;
            default :
                throw new Exception('Unknown feedback type');
        }

        $hash = spl_object_hash($object);

        if(isset($this->messages[$hash][$type])) {
            return $this->messages[$hash][$type];
        }

        return array();
    }

    public function getWarningMessages($object) {
        return $this->getMessages($object, self :: FEEDBACK_WARNING);
    }

    public function getErrorMessages($object) {
        return $this->getMessages($object, self :: FEEDBACK_ERROR);
    }

    public function getDebugMessages($object) {
        return $this->getMessages($object, self :: FEEDBACK_DEBUG);
    }

    public function getInfoMessages($object) {
        return $this->getMessages($object, self :: FEEDBACK_DEBUG);
    }
}

abstract class FeedbackMessage extends ParameterizedMessage {

    public function __toString() {
        return $this->message;
    }

}

class InfoMessage extends FeedbackMessage {

}

class DebugMessage extends FeedbackMessage {

}

class WarningMessage extends FeedbackMessage {

}

class ErrorMessage extends FeedbackMessage {

}